import BaseView from "../cfw/mvc/BaseView";
import BaseModel from "../cfw/mvc/BaseModel";
import ResLoader from "../cfw/res/ResLoader";
import { ResType } from "../cfw/res/ResInterface";
import ResItem from "../cfw/res/ResItem";
import BaseController from "../cfw/mvc/BaseController";
import TSMap from "../cfw/struct/TSMap";
import GlobalEvent from "../cfw/event/GlobalEvent";
import { UIIndex } from "../cfw/tools/Define";

export default class ViewManager {


    private viewMap: TSMap<string, boolean> = new TSMap()

    private static ins: ViewManager;

    static instance() {
        if (!this.ins) {
            this.ins = new ViewManager()
        }
        return this.ins;
    }

    constructor() {
        GlobalEvent.instance().on(GlobalEvent.POP_VIEW, this.popView, this)
    }

    popView() {

    }

    remove(key: string) {
        this.viewMap.remove(key)
    }

    /**
     *
     * 使用预制体的名称初始化节点，主要目的时给view传递controller和model
     * @param node 节点 可以是cc.instance()的，也可以是重PoolManager获取的。
     * @param name 组件的名称
     * @param model 模型数据。
     */
    initView(node: cc.Node, name, c: BaseController, model?: BaseModel) {
        let component: BaseView = node.getComponent(name);
        if (!component) {
            component = node.addComponent(name);
        }
        component.setController(c);
        if (model) {
            component.setModel(model);
        }
        return component;
    }


    /**
     * 
     * @param prefab 
     * @param className 
     * @param c 
     * @param model 
     * @param parent 
     * @param func 
     */
    addPrefabToParent(prefab: cc.Prefab, className: string, c: BaseController, model: any, parent: cc.Node, func?: Function) {
        let node = cc.instantiate(prefab)
        let component = this.initView(node, className, c, model);
        if (component) {
            if (cc.isValid(parent)) {
                // parent.addChild(node);
                node.parent = parent;
            }
            if (func) {
                func(component);
            }
        } else {
            cc.warn(" comp is null ", name);
            if (func) {
                func(null);
            }
        }

    }

    /**
     * 
     * @param prefab 
     * @param className 
     * @param c 
     * @param model 
     * @param uiIndex 
     */
    pushPrefab(prefab: cc.Prefab, className: string, c: BaseController, model?: BaseModel, uiIndex: UIIndex = UIIndex.STACK) {
        let node = cc.instantiate(prefab)
        let component = this.initView(node, className, c, model);
        if (component) {
            component.setUIIndex(uiIndex)
            component.show();
            return component
        } else {
            cc.warn(" comp is null ", name);
            return null;
        }

    }


    /**
     * 
     * @param prefab 
     * @param className 
     * @param model 
     * @param parent 
     * @param loader 
     * @param func 
     */
    addToParent(prefab: string, className: string, c: BaseController, model: any, loader: ResLoader, parent: cc.Node, func?: Function) {
        this.getPrefab(prefab, loader, (err, prefab: cc.Prefab) => {
            if (err) {
                cc.log(" pushView err " + err + "  name " + prefab);
                if (func) {
                    func(null);
                }
                return;
            }
            this.addPrefabToParent(prefab, className, c, model, parent, func)
        })
    }



    pushToast(prefab: string, className: string, c: BaseController, model: any, loader: ResLoader, uiIndex: UIIndex = UIIndex.STACK, func?: Function) {
        this.getPrefab(prefab, loader, (err, prefab: cc.Prefab) => {
            if (err) {
                cc.log(" pushView err " + err + "  name " + prefab);
                if (func) {
                    func(null);
                }
                return;
            }
            let component = this.pushPrefab(prefab, className, c, model, uiIndex)
            if (component) {
                if (func) {
                    func(component);
                }
            } else {
                cc.warn(" comp is null ", name);
                if (func) {
                    func(null);
                }
            }
        })
    }
    /**
     * 将ui添加到管理器中。
     * @param prefab 预制体麓景
     * @param className 组件类型
     * @param model 模型
     * @param uiIndex ui管理器层级
     * @param loader 加载器
     * @param func 加载成功回调
     */
    pushView(prefab: string, className: string, c: BaseController, model: any, loader: ResLoader, uiIndex: UIIndex = UIIndex.STACK, func?: Function) {
        if (this.viewMap.has(prefab)) {
            console.warn(' pushVIew  ', this.viewMap.has(prefab))
            return;
        }
        this.viewMap.set(prefab, 1)
        setTimeout(() => {
            this.viewMap.delete(prefab)
        }, 1000);
        this.pushToast(prefab, className, c, model, loader, uiIndex, (comp) => {
           
            if (func) {
                func(comp)

            }
        })

    }

    /**
     * 
     * @param prefabName 预制体的名称
     * @param callback 加载后的回调。
     */
    getPrefab(prefabName: string, loader: ResLoader, callback: (err: string, node?: cc.Prefab) => void) {
        let resName = "";
        if (prefabName.indexOf("/") >= 0) {
            resName = prefabName;
            let list = prefabName.split("/");
            prefabName = list[list.length - 1];
        } else {
            resName = "prefabs/" + prefabName;
        }

        loader.loadRes(resName, ResType.Prefab,
            (err, item: ResItem) => {
                if (err) {
                    callback(" UIManager getComponent err " + err);
                    return;
                }
                //这里可以配合对象池使用。
                // let node = cc.instantiate(item.getRes())
                // if (node) {
                callback(null, item.getRes());
                // } else {
                //     callback("node is null");
                // }
            });
    }
    getClassName(prefabName) {
        let className = "";
        if (prefabName.indexOf("/") >= 0) {
            let list = prefabName.split("/");
            className = list[list.length - 1];
        } else {
            className = prefabName;
        }
        return className;
    }
}
